package meadow;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

import uk.ac.nott.cs.g53dia.Bee;
import uk.ac.nott.cs.g53dia.Cell;
import uk.ac.nott.cs.g53dia.DefaultBeeViewerIconFactory;
import uk.ac.nott.cs.g53dia.Flower;
import uk.ac.nott.cs.g53dia.Nest;
import uk.ac.nott.cs.g53dia.Point;
import utils.General;
import valueobj.GlobalState;
import valueobj.IndexPair;

public class Meadow extends JPanel {

//  private JPanel[][] cellsLayer0;
//  private JLabel[][] cellsLayer1;
  
  private List<List<JPanel>> cellsLayer0;
  private List<List<JLabel>> cellsLayer1;
  public static int width, height, rows, columns; 
  public static int maximumX;
  public static int maximumY;
  private Map<Bee, IndexPair> beeMap;
  private Map<Bee, IndexPair> toDelete;
  DefaultBeeViewerIconFactory iconfactory;
  private JFrame parent;
  private boolean[][] visited;
  private boolean[][] nests;

  public Meadow(int width, int height, int rows, int cols, GlobalState state, final JFrame parent) {
    this.parent = parent;
    Meadow.width = width;
    Meadow.height = height;
    setSize(width, height);
    Meadow.rows = rows;
    Meadow.columns = cols;
    setLayout(new GridLayout(rows, cols));
    iconfactory = new DefaultBeeViewerIconFactory();
    Map<Point, Cell> cells = state.getCells();
    beeMap = new HashMap<Bee, IndexPair>();
    toDelete = new HashMap<Bee, IndexPair>();
    for (Bee bee : state.getSwarm()) {
      beeMap.put(bee/*.clone()*/, General.getIndexPairForMeadow(bee.getPosition()));
    }

//    cellsLayer0 = new JPanel[columns][rows];
//    cellsLayer1 = new JLabel[columns][rows];
    cellsLayer0 = new ArrayList<List<JPanel>>(columns);
    for (int i = 0; i <= rows; i ++) {
      cellsLayer0.add(new ArrayList<JPanel>(rows));
    }
    cellsLayer1 = new ArrayList<List<JLabel>>(columns);
    for (int i = 0; i <= rows; i ++) {
      cellsLayer1.add(new ArrayList<JLabel>(rows));
    }
    
    for (int i = 0; i <= rows; i ++) {
      for (int j = 0; j <= columns; j ++) {
        cellsLayer0.get(i).add(new JPanel());
        cellsLayer0.get(i).get(j).setPreferredSize(new Dimension(17,17));
        cellsLayer1.get(i).add(new JLabel());
//        cellsLayer1.get(i).get(j).setPreferredSize(new Dimension(5,5));
      }  
    }
    
    visited = new boolean[columns+1][rows+1];
    nests = new boolean[columns+1][rows+1];
    for (int j = 0; j < rows; j++) {
      final int indJ = j;
      for (int i = 0; i < columns; i++) {
        final int indI = i;
        Point p = General.getPointForMeadow(new IndexPair(i, j));
        Cell cell = cells.get(p);
        visited[i][j] = true;
//        cellsLayer0.get(i).get(j) = new JPanel());
        cellsLayer0.get(i).get(j).setBorder(BorderFactory.createLineBorder(Color.DARK_GRAY, 1));
//        cellsLayer0[i][j].setSize(6, 6);
        
        if (cell instanceof Flower) {
          int type = ((Flower) cell).getType();
          switch (type) {
          case 0:
            cellsLayer0.get(i).get(j).setBackground(Color.blue);
            cellsLayer0.get(i).get(j).setToolTipText(String.valueOf(((Flower) cell).getNumFlowers()));
            break;
          case 1:
            cellsLayer0.get(i).get(j).setBackground(Color.cyan);
            cellsLayer0.get(i).get(j).setToolTipText(String.valueOf(((Flower) cell).getNumFlowers()));
            break;
          case 2:
            cellsLayer0.get(i).get(j).setBackground(Color.pink);
            cellsLayer0.get(i).get(j).setToolTipText(String.valueOf(((Flower) cell).getNumFlowers()));
            break;
          case 3:
            cellsLayer0.get(i).get(j).setBackground(Color.red);
            cellsLayer0.get(i).get(j).setToolTipText(String.valueOf(((Flower) cell).getNumFlowers()));
            break;
          case 4:
            cellsLayer0.get(i).get(j).setBackground(Color.orange);
            cellsLayer0.get(i).get(j).setToolTipText(String.valueOf(((Flower) cell).getNumFlowers()));
            break;
          }
        }
        Cell cellVisited = state.getCellsVisited().get(p);
        if (cellVisited instanceof Nest) {
          cellsLayer0.get(i).get(j).setBackground(Color.black);
          nests[i][j] = true;
        } else if (cellVisited == null) {
          cellsLayer0.get(i).get(j).setBackground(Color.gray);
          visited[i][j] = false;
        }

        cellsLayer0.get(i).get(j).addMouseListener(new MouseListener() {

          public void mouseClicked(MouseEvent e) {
            Point point = General.getPointForMeadow(new IndexPair(indI, indJ));
            JOptionPane.showMessageDialog(parent, /*"(" + indI + ", " + indJ + ") ~ */"[" + point.x + "," + point.y + "]");
          }

          public void mouseEntered(MouseEvent e) {
            Point point = General.getPointForMeadow(new IndexPair(indI, indJ));
            ((MeadowWrapper) parent).getInfo().setText(
                /*"(" + indI + ", " + indJ + ") ~ */"[" + point.x + "," + point.y + "]");
          }

          public void mouseExited(MouseEvent e) {
          }

          public void mousePressed(MouseEvent e) {
          }

          public void mouseReleased(MouseEvent e) {
          }

        });
        cellsLayer1.get(i).get(j).add(new JLabel("", JLabel.CENTER));
//        cellsLayer1[i][j].setSize(6, 6);
        cellsLayer0.get(i).get(j).add(cellsLayer1.get(i).get(j));
        add(cellsLayer0.get(i).get(j));
      }
    }
  }
  

  public void update(Bee bee, Cell[][] cells) {
    IndexPair lastPos = beeMap.get(bee);
    IndexPair actualPos = General.getIndexPairForMeadow(bee.getPosition());
    IndexPair delete = toDelete.get(bee);
    if (delete != null && !actualPos.equals(delete)) {
      cellsLayer1.get(delete.getX()).get(delete.getY()).setIcon(null);
    }
    if (lastPos.equals(actualPos)) { // no movement
      cellsLayer1.get(lastPos.getX()).get(lastPos.getY()).setIcon(iconfactory.getIconForSmallBee(bee));
    } else {
      toDelete.put(bee.clone(), lastPos);
      cellsLayer1.get(lastPos.getX()).get(lastPos.getY()).setIcon(iconfactory.getIconForSmallBeeAl(bee));
      cellsLayer1.get(actualPos.getX()).get(actualPos.getY()).setIcon(iconfactory.getIconForSmallBee(bee));
    }

    beeMap.put(bee/*.clone()*/, General.getIndexPairForMeadow(bee.getPosition()));

    for (Cell[] cellRow : cells) {
      for (Cell cell : cellRow) {
        IndexPair ip = General.getIndexPairForMeadow(cell.getPoint());
        boolean isIn = visited[ip.getX()][ip.getY()];
        if (isIn && !(nests[ip.getX()][ip.getY()]) && (cell instanceof Nest)) {
          // System.out.println("new nest");
          nests[ip.getX()][ip.getY()] = true;
          cellsLayer0.get(ip.getX()).get(ip.getY()).setBackground(Color.black);
        } else if (!isIn) {
          visited[ip.getX()][ip.getY()] = true;
          if (cell instanceof Flower) {
            int type = ((Flower) cell).getType();
            switch (type) {
            case 0:
              cellsLayer0.get(ip.getX()).get(ip.getY()).setBackground(Color.blue);
              break;
            case 1:
              cellsLayer0.get(ip.getX()).get(ip.getY()).setBackground(Color.cyan);
              break;
            case 2:
              cellsLayer0.get(ip.getX()).get(ip.getY()).setBackground(Color.pink);
              break;
            case 3:
              cellsLayer0.get(ip.getX()).get(ip.getY()).setBackground(Color.red);
              break;
            case 4:
              cellsLayer0.get(ip.getX()).get(ip.getY()).setBackground(Color.orange);
              break;
            }
          } else {
            cellsLayer0.get(ip.getX()).get(ip.getY()).setBackground(Color.white);
          }
        }
      }
    }
//    repaint();
  }

}